科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件Observer模式深度探索

Observer模式深度探索

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

Observer模式是经典设计模式中应用最为广泛也最为灵活多变的模式之一。本文在.NET技术框架下深入发掘了Observer模式的内涵

作者:Doug Purdy Jeffrey Richter 来源:程序员》杂志 2007年11月8日

关键字: Windows

  • 评论
  • 分享微博
  • 分享邮件
观察者示例(C#)

//represents a stock in an application
public class Stock:ObservableImpl {

//instance variable for ask price
object _askPrice;

//property for ask price
public object AskPrice {

set { _askPrice=value;
base.NotifyObservers(_askPrice);
}//set

}//AskPrice property

}//Stock

//represents the user interface in the application
public class StockDisplay:IObserver {

public void Notify(object anObject){
Console.WriteLine("The new ask price is:" + anObject);
}//Notify

}//StockDisplay

public class MainClass{

public static void Main() {

//create new display and stock instances
StockDisplay stockDisplay=new StockDisplay();
Stock stock=new Stock();

//register the grid
stock.Register(stockDisplay);

//loop 100 times and modify the ask price
for(int looper=0;looper < 100;looper++) {
stock.AskPrice=looper;
}

//unregister the display
stock.UnRegister(stockDisplay);

}//Main

}//MainClass

  .NET框架中的Observer模式

  基于我们对Observer模式的了解,让我们将注意力转向此模式在.NET框架中的使用情况。您们当中非常熟悉FCL中所公开类型的人将会注意到,框架中没有IObserver、IObservable或ObservableImpl类型。虽然您的确可以在.NET应用程序中使用这些构造,但引入委托和事件可提供新的、功能强大的方法来实现Observer模式,而不必开发专用于支持该模式的特定类型。事实上,因为委托和事件是CLR的一级成员,所以将此模式的基本构造添加到.NET框架的核心中。因此,FCL在其结构中广泛使用Observer模式。

  介绍委托和事件内部工作方式的文章非常多,我们在此不再赘述。我们只需说明委托是面向对象(和类型安全)版的函数指针就够了。委托实例保存对实例或类方法的引用,允许匿名调用绑定方法。事件是在类上声明的特殊构造,可在运行时发布被关注对象的状态变化。事件表示我们前面用于实现Observer模式的注册、撤消注册和通知方法的形式抽象(CLR和多种不同的编译器对它提供支持)。委托是在运行时注册到特定事件中的。在引发事件时,将调用所有注册的委托,以使它们能够收到事件的通知。

  按照Observer模式定义的术语,声明事件的类就是主体。与我们以前使用的IObservable接口和ObservableImpl类不同,主体类不需要实现给定接口或扩展基类。主体只需要公开一个事件,而不需要执行任何其他操作。观察者创建的工作略多一些,但灵活性却提高得非常多(我们将在后面讨论)。观察者并不实现IObserver接口和将其自身注册到主体中,而是必须创建特定的委托实例,并将此委托注册到主体事件中。观察者必须使用具有事件声明所指定类型的委托实例,否则,注册就会失败。在创建此委托实例的过程中,观察者将传递该主体向委托通知的方法(实例或静态)名称。在将委托绑定到方法后,可以将其注册到主体的事件中。类似地,也可以从事件中撤消注册此委托。主体通过调用事件向观察者提供通知。

  如果您不熟悉委托和事件,则实现Observer模式似乎需要做很多工作,尤其是与我们以前使用的IObserver和IObservable接口相比。但是,它比听起来要简单一些,并且实现起来要容易得多。下面的C#和Visual Basic .NET代码示例重点说明了在我们的示例应用程序中支持委托和事件所需的类修改。注意,没有Stock或StockDisplay类用于支持该模式的任何基类或接口。

  使用委托和事件的观察者(C#)

public class Stock {

//declare a delegate for the event
public delegate void AskPriceDelegate(object aPrice);
//declare the event using the delegate
public event AskPriceDelegate AskPriceChanged;

//instance variable for ask price
object _askPrice;

//property for ask price
public object AskPrice {

set {
//set the instance variable
_askPrice=value;

//fire the event
AskPriceChanged(_askPrice);
}

}//AskPrice property

}//Stock class

//represents the user interface in the application
public class StockDisplay {

public void AskPriceChanged(object aPrice) {
Console.Write("The new ask price is:" + aPrice + "\r\n"); }

}//StockDispslay class

public class MainClass {

public static void Main(){

//create new display and stock instances
StockDisplay stockDisplay=new StockDisplay();
Stock stock=new Stock();

//create a new delegate instance and bind it
//to the observer's askpricechanged method
Stock.AskPriceDelegate aDelegate=new
Stock.AskPriceDelegate(stockDisplay.AskPriceChanged);

//add the delegate to the event
stock.AskPriceChanged+=aDelegate;

//loop 100 times and modify the ask price
for(int looper=0;looper < 100;looper++) {
stock.AskPrice=looper;
}

//remove the delegate from the event
stock.AskPriceChanged-=aDelegate;

}//Main

}//MainClass

  在熟悉了委托和事件后,您就会清楚地看到它们的巨大潜力。与IObserver和IObservable接口以及ObservableImpl类不同,使用委托和事件可大大减少实现此模式所需的工作量。CLR和编译器为观察者容器管理提供了基础,并且为注册、撤消注册和通知观察者提供了一个通用调用约定。也许,委托的最大优点是其能够引用任何方法的固有特性(条件是它符合相同的签名)。这允许任何类用作观察者,而与它所实现的接口或它专用的类无关。虽然使用IObserver和IObservable接口可减少观察者和主体类之间的耦合关系,但使用委托可完全消除这些耦合关系。
    • 评论
    • 分享微博
    • 分享邮件
    闂傚倸鍊风欢锟犲矗鎼淬劌绐楅柡鍥╁亹閺嬪酣鏌曡箛瀣仾濠殿垰銈搁弻鏇$疀鐎n亖鍋撻弽顓ㄧ稏闁跨噦鎷�

    婵犵數濮烽。浠嬪焵椤掆偓閸熷潡鍩€椤掆偓缂嶅﹪骞冨Ο璇茬窞闁归偊鍓涢悾娲⒑闂堟单鍫ュ疾濠婂嫭鍙忔繝濠傜墛閸嬨劍銇勯弽銊с€掗柟钘夊暣閺岀喖鎮滈埡鍌涚彋閻庤娲樺畝绋跨暦閸洖鐓涢柛灞剧矋濞堟悂姊绘担绛嬪殐闁搞劋鍗冲畷銏ゅ冀椤愩儱小闂佹寧绋戠€氼參宕伴崱妯镐簻闁靛牆鎳庢慨顒€鈹戦埥鍡椾簼婵犮垺锚铻炴俊銈呮噺閸嬪倹绻涢崱妯诲碍閻庢艾顦甸弻宥堫檨闁告挾鍠庨锝夘敆娓氬﹦鐭楁繛鎾村焹閸嬫捇鏌e☉娆愬磳闁哄本绋戦埞鎴﹀川椤曞懏鈻婄紓鍌欑劍椤ㄥ懘鎯岄崒鐐靛祦閹兼番鍔岄悞鍨亜閹烘垵顏╅悗姘槹閵囧嫰寮介妸褎鍣ョ紓浣筋嚙濡繈寮婚悢纰辨晣鐟滃秹鎮橀懠顒傜<閺夊牄鍔庣粻鐐烘煛鐏炶姤鍠橀柡浣瑰姍瀹曠喖顢橀悩铏钒闂備浇宕垫慨鎶芥⒔瀹ュ鍨傞柦妯猴級閿濆绀嬫い鏍ㄧ☉濞堟粓姊虹涵鍛【妞ゎ偅娲熼崺鈧い鎺嗗亾闁挎洩濡囧Σ鎰板籍閸繄顓洪梺缁樺姇瀵剙螖閸涱喚鍘搁梺鍓插亽閸嬪嫰鎮橀敃鍌涚厱閻庯綆鍋嗘晶顒傜磼閸屾稑绗ч柟鐟板閹煎湱鎲撮崟闈涙櫏闂傚倷绀侀幖顐も偓姘卞厴瀹曞綊鏌嗗鍛紱閻庡箍鍎遍ˇ浼村磿瀹ュ鐓曢柡鍥ュ妼婢ь垰霉閻樿秮顏堟箒闂佹寧绻傚Λ妤呭煝閺囥垺鐓冪憸婊堝礈濮樿泛钃熼柕濞у嫷鍋ㄩ梺缁樺姇椤曨參鍩㈤弴銏″€甸柨婵嗗€瑰▍鍥ㄣ亜韫囨稐鎲鹃柡灞炬礋瀹曢亶顢橀悢濂変紦

    重磅专题
    往期文章
    最新文章